import warnings

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

warnings.filterwarnings('ignore')

# 设置中文字体和样式
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# sns.set_style("whitegrid")


class SupplyChainAnalyzer:
    def __init__(self, df):
        self.df = df.copy()
        self.analysis_results = {}

    def data_view(self):
        print('=' * 50)
        print('数据预览')
        print('=' * 50)

        print(f'数据及形状:{self.df.shape}')
        print(f'\n字段类型:{self.df.dtypes}')

        print(f'\n基本统计信息')
        print(self.df.describe())

        print(f'\n缺失值检查')
        missing_data = self.df.isnull().sum()
        print(missing_data[missing_data > 0])

    def data_clean(self):
        print("\n" + "=" * 50)
        print("数据清洗")
        print("=" * 50)

        # 检查重复行
        duplicates = self.df.duplicated().sum()
        print(f'重复行数量L{duplicates}')

        if duplicates > 0:
            self.df.drop_duplicates()
            print(f'已删除重复行，新形状：{self.df.shape}')

        print(f'交付时间最小为：{self.df["LEAD_TIME"].min()}，最大为：{self.df["LEAD_TIME"].max()}')

        return self.df

    def supply_chain_analysis(self):
        print("\n" + "=" * 50)
        print("供应链分析")
        print("=" * 50)

        # 按商品类别分析提前期
        lead_time_by_commodity = self.df.groupby('COMMODITY')["LEAD_TIME"].agg(
            ['count', 'mean', 'std', 'min', 'max']).round(2).sort_values('mean', ascending=False)
        print("各商品类别的提前期统计:")
        print(lead_time_by_commodity)

        # 按CCN别分析提前期
        lead_time_by_ccn = self.df.groupby('CCN')["LEAD_TIME"].agg(
            ['count', 'mean', 'std', 'min', 'max']).round(2).sort_values('mean', ascending=False)
        print("各CCN的提前期统计:")
        print(lead_time_by_ccn)

        # 按供应链类型别分析
        supply_chain_type = self.df['SUPPLY_CHAIN_TYPE'].value_counts()
        print(f"按供应链类型别分析:{supply_chain_type}")

        self.analysis_results['lead_time_by_commodity'] = lead_time_by_commodity
        self.analysis_results['lead_time_by_ccn'] = lead_time_by_ccn

        return lead_time_by_commodity

    def product_portfolio_analysis(self):
        print("\n" + "=" * 50)
        print("产品组合分析")
        print("=" * 50)

        # 商品类别分布
        commodity_dist = self.df['COMMODITY'].value_counts()
        print(f'商品类型分布：{commodity_dist}')

        ccn_dist = self.df['CCN'].value_counts()
        print(f'CCN分布：{ccn_dist}')

        supply_chain_type = self.df['SUPPLY_CHAIN_TYPE'].value_counts()
        print(f'供应链类型别分析：{supply_chain_type}')

        self.analysis_results['commodity_dist'] = commodity_dist
        self.analysis_results['ccn_dist'] = ccn_dist

        return commodity_dist

    def risk_analysis(self):
        print("\n" + "=" * 50)
        print("供应链风险分析")
        print("=" * 50)

        # 风险分类
        def categorize_risk(lead_time):
            if lead_time <= 7:
                return 'low risk'
            elif lead_time <= 15:
                return 'medium risk'
            else:
                return 'high risk'

        self.df['RISK_LEVEL'] = self.df['LEAD_TIME'].apply(categorize_risk)

        risk_analysis = self.df.groupby(['COMMODITY', 'RISK_LEVEL']).size().unstack(fill_value=0)
        risk_analysis['TOTAL'] = risk_analysis.sum(axis=1)
        risk_analysis = risk_analysis.sort_values(by='TOTAL', ascending=False)
        print("各商品类别的风险等级分布:")
        print(risk_analysis)

        # 高风险商品识别
        high_risk_items = self.df[self.df['RISK_LEVEL'] == 'high risk']
        print(f"\n高风险商品数量: {len(high_risk_items)}")
        print("高风险商品列表:")
        print(high_risk_items[['COMMODITY', 'RISK_LEVEL', 'ITM_DESC']].head(10))

        self.analysis_results['high_risk_items'] = high_risk_items
        self.analysis_results['risk_analysis'] = risk_analysis

        return risk_analysis

    def create_plot(self):
        print("\n" + "=" * 50)
        print("生成可视化图表")
        print("=" * 50)

        fig, axes = plt.subplots(2, 3, figsize=(18, 12))
        fig.suptitle('供应链数据分析仪表板', fontsize=16, fontweight='bold')

        # 1、商品类别分布
        commodity_top10 = self.analysis_results['commodity_dist'].head(10)
        axes[0, 0].barh(commodity_top10.index, commodity_top10.values)
        axes[0, 0].set_title('Top 10 商品类别分布')
        axes[0, 0].set_xlabel('数量')

        # 2、提前期分布
        axes[0, 1].hist(self.df['LEAD_TIME'], bins=15, alpha=0.7, color='skyblue', edgecolor='black')
        axes[0, 1].set_title('提前期分布')
        axes[0, 1].set_xlabel('提前期(天)')
        axes[0, 1].set_ylabel('频次')

        # 3、风险等级分布
        risk_dist = self.df['RISK_LEVEL'].value_counts()
        axes[0, 2].pie(risk_dist.values, labels=risk_dist.index, autopct='%1.1f%%', startangle=90)
        axes[0, 2].set_title('风险等级分布')

        # 4. 各商品类别平均提前期
        lead_time_means = self.analysis_results['lead_time_by_commodity'].head(10).mean()
        axes[1, 0].barh(lead_time_means.index, lead_time_means.values, color='salmon')
        axes[1, 0].set_title('各商品类别平均提前期(Top 10)')
        axes[1, 0].set_xlabel('平均提前期(天)')

        # 5. 供应链类型分布
        chain_dist = self.df['SUPPLY_CHAIN_TYPE'].value_counts()
        axes[1, 1].barh(chain_dist.index, chain_dist.values, color=['#ff9999', '#66b3ff', '#99ff99'])
        axes[1, 1].set_title('供应链类型分布')
        axes[1, 1].set_ylabel('数量')

        # 6、CCN分布
        ccn_top8 = self.analysis_results['ccn_dist'].head(8)
        axes[1, 2].bar(ccn_top8.index, ccn_top8.values, color='lightgreen')
        axes[1, 2].set_title('CCN分布(Top 8)')
        axes[1, 2].set_ylabel('数量')
        axes[1, 2].tick_params(axis='x', rotation=45)

        plt.tight_layout()
        plt.savefig('imageRes/supply_chain_analysis.png', dpi=300, bbox_inches='tight')
        # plt.show()

        plt.figure(figsize=(12, 8))
        risk_pivot = self.df.pivot_table(index='COMMODITY', columns='RISK_LEVEL', values='COMP_ITEM_ID',
                                         aggfunc='count', fill_value=0)

        # 只显示有数据的商品类别
        risk_pivot = risk_pivot[risk_pivot.sum(axis=1) > 0]

        sns.heatmap(risk_pivot, annot=True, fmt='d', cmap='YlOrRd', linewidths=0.5)
        plt.title('商品类别风险等级热力图')
        plt.tight_layout()
        plt.savefig('imageRes/risk_heatmap.png', dpi=300, bbox_inches='tight')
        # plt.show()

    # 这个是抄的，不知道他干了啥
    def advanced_supply_chain_opt(self):
        print("\n" + "=" * 50)
        print("高级供应链优化分析")
        print("=" * 50)

        # 1. ABC分类分析
        commodity_importance = self.df.groupby('COMMODITY').agg({
            'LEAD_TIME': 'mean',
            'COMP_ITEM_ID': 'count'
        }).rename(columns={'COMP_ITEM_ID': 'ITEM_COUNT'})

        # 基于提前期和数量进行ABC分类
        commodity_importance['SCORE'] = (
                commodity_importance['LEAD_TIME'] * 0.7 +
                commodity_importance['ITEM_COUNT'] * 0.3
        )
        commodity_importance['ABC_CLASS'] = pd.qcut(
            commodity_importance['SCORE'],
            3,
            labels=['C类', 'B类', 'A类']
        )

        print("ABC分类分析结果:")
        print(commodity_importance.sort_values('SCORE', ascending=False))

        self.analysis_results['commodity_importance'] = commodity_importance
        return commodity_importance

    def generate_recommendation(self):
        print("\n" + "=" * 50)
        print("供应链优化建议")
        print("=" * 50)

        high_risk_items = self.analysis_results['high_risk_items']
        lead_time_stats = self.analysis_results['lead_time_by_commodity']

        print('1、高风险关注想：')
        high_risk_commodities = high_risk_items['COMMODITY'].value_counts()
        for commodity, count in high_risk_commodities.items():
            avg_lead_time = lead_time_stats.loc[commodity, 'mean']
            print(f"   • {commodity}: {count}个商品，平均提前期 {avg_lead_time}天")

        print("\n2、库存策略建议:")
        # 基于提前期给出库存策略
        for commodity in lead_time_stats.index:
            avg_lead_time = lead_time_stats.loc[commodity, 'mean']
            count = lead_time_stats.loc[commodity, 'count']

            if avg_lead_time > 15:
                strategy = "安全库存 + 多供应商策略"
            elif avg_lead_time > 7:
                strategy = '适度安全库存'
            else:
                strategy = '准时制库存'

            # 大于5的样本才显示
            if count >= 5:
                print(f"   • {commodity}: {strategy} (平均{avg_lead_time}天)")

        print("\n3、数据质量改进建议:")
        # 检查数据质量问题
        duplicate_cfgs = self.df['CFG'].duplicated().sum()
        if duplicate_cfgs > 0:
            print(f"   • 发现 {duplicate_cfgs} 个重复的CFG配置，建议标准化")

    def get_analysis_res(self):
        print("开始供应链数据分析...")
        self.data_view()
        self.data_clean()
        self.supply_chain_analysis()
        self.product_portfolio_analysis()
        self.risk_analysis()
        self.create_plot()
        self.advanced_supply_chain_opt()
        self.generate_recommendation()
        print("\n分析完成！")

        return self.analysis_results
